package scales.xml.dsl
import scales.xml.{
XmlTree, Elem,
XCC, XmlItem,
QName, ScalesXml,
Attribute, emptyChildren,
ItemOrElem, XPath,
XmlPath, Text, raw
}
import scales.utils.collection.path._
import scales.utils.{AsBoolean, subtree, foldPositions, booleanMatcher, booleanAndTMatcher, top, item}
import ScalesXml.xmlCBF
import ScalesXml.fromParserDefault
object DslBuilder {
def elem2tree( elem : Elem ) : XmlTree = subtree[XmlItem, Elem, XCC](elem,emptyChildren).right.get
def q2tree( qname : QName ) = elem2tree(Elem(qname))
def apply( qname : QName ) = new DslBuilder(elem2tree(Elem(qname)))
def apply( elem : Elem ) = new DslBuilder(elem2tree(elem))
def apply( tree : XmlTree ) = new DslBuilder(tree)
}
case class FoldErrorException(error : FoldError) extends RuntimeException
final class DslBuilder private(val tree: XmlTree) {
import ScalesXml._
def /@(attribs : Attribute*) = new DslBuilder( tree.copy(section = tree.section.copy (attributes = tree.section.attributes ++ attribs) ))
def /@(attribs : => Iterable[Attribute]) : DslBuilder = new DslBuilder( tree.copy(section = tree.section.copy (attributes = tree.section.attributes ++ attribs) ))
def /@(attrib : Option[Attribute]) =
attrib.map{ a =>
new DslBuilder( tree.copy(section = tree.section.copy (attributes = tree.section.attributes + a) ))
}.getOrElse{this}
def -/@(attribs : QName*) = new DslBuilder( tree.copy(section = tree.section.copy (attributes = tree.section.attributes -- attribs)))
def add( itemOrElems : ItemOrElem * ) = /( itemOrElems :_* )
def /( itemOrElems : => Iterable[ItemOrElem] ) : DslBuilder =
new DslBuilder( tree.copy( children = (tree.children ++ itemOrElems )))
def addOptionals( itemOrElems : Option[ItemOrElem] * ) : DslBuilder = /( itemOrElems.flatten )
def addOptionals( itemOrElems : => Iterable[Option[ItemOrElem]] ) : DslBuilder =
/(itemOrElems.flatten)
def /( itemOrElem : Option[ItemOrElem] ) =
itemOrElem.map{ i =>
new DslBuilder( tree.copy( children = (tree.children :+ i )))
}.getOrElse{this}
def fold[T <: Iterable[XmlPath]]( xpath : XmlPath => XPath[T])( folder: (XmlPath) => FoldOperation[XmlItem, Elem, XCC] ) : Either[DslBuilder, (DslBuilder, FoldError)] =
(foldPositions( raw( xpath( top(tree) ) ) )(folder)).
fold( x => Left(new DslBuilder( x.tree )), y => Right((this,y)) )
def fold_![T <: Iterable[XmlPath]]( xpath : XmlPath => XPath[T])( folder: (XmlPath) => FoldOperation[XmlItem, Elem, XCC] ) : DslBuilder =
(fold(xpath)(folder)).fold(identity, x => throw new FoldErrorException(x._2))
def fold_?[T <: Iterable[XmlPath]]( xpath : XmlPath => XPath[T])( folder: (XmlPath) => FoldOperation[XmlItem, Elem, XCC] ) : DslBuilder =
(fold(xpath)(folder)).fold(identity, x =>
if (x._2 eq NoPaths)
this
else throw new FoldErrorException(x._2))
def -/( qname : QName ) = new DslBuilder(tree.copy(children = tree.children.filterNot{
either =>
either.fold( item => false, tree => tree.section.name =:= qname)
}))
def /( itemOrElems : ItemOrElem * ) =
new DslBuilder( tree.copy( children = (tree.children ++ itemOrElems )))
def ~>( value : String ) : DslBuilder =
if (value ne null)
new DslBuilder( tree.copy(children = emptyChildren :+ item[XmlItem, Elem, XCC](Text(value))))
else this
def setValue( value : String ) = ~>(value)
def ~>( value : Option[String] ) : DslBuilder =
value.map{ v =>
new DslBuilder( tree.copy(children = emptyChildren :+ item[XmlItem, Elem, XCC](Text(v))))
}.getOrElse{this}
def setValue( value : Option[String] ) = ~>(value)
def elementsOnly = new DslBuilder(tree.copy(children = tree.children.filter( _.fold( _ => false, _ => true ) ) ))
def toTree = tree
}
<iframe src="https://scalesxml.github.io/scales-xml_2.10/0.5.0/api.sxr/scales/xml/dsl/DslBuilder.scala.html" width="1280" height="720" frameborder="0"> </iframe>